﻿using Co9320.NamaAlert.CommunicationControl;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Co9320.NamaAlert.Model.TagServer;
using Co9320.NamaAlert.Model;

namespace TagServiceTest
{
    
    
    /// <summary>
    ///RequestTransactorTest のテスト クラスです。すべての
    ///RequestTransactorTest 単体テストをここに含めます
    ///</summary>
	[TestClass()]
	public class RequestTransactorTest
	{
		private class TagValues
		{
			public string StationId;
			public string Caster;
			public List<TagModel> Tags;

			public TagValues()
			{
				StationId = null;
				Caster = null;
				Tags = new List<TagModel>();
			}

		}

		private static int IdSeed = 0;

		private TestContext testContextInstance;
		private OneWayTransactor Target;

		/// <summary>
		///現在のテストの実行についての情報および機能を
		///提供するテスト コンテキストを取得または設定します。
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}



		#region 追加のテスト属性
		[TestInitialize()]
		public void MyTestInitialize()
		{
			Target = new OneWayTransactor();
		}
		#endregion



		/// <summary>
		///GetParameters のテスト
		///</summary>
		[TestMethod()]
		public void GetParametersTest()
		{
			ParametersCollection collection = Target.GetParameters();
			Assert.IsNull(collection.GetAddParameters());
			Assert.IsNull(collection.GetDeleteParameters());
			Assert.IsNull(collection.GetModifyParameters());
		}

		/// <summary>
		///Delete のテスト
		///</summary>
		[TestMethod()]
		public void DeleteTest()
		{
			var Sample = GetSample(1);

			Target.Delete(Sample.StationId, Sample.Caster, Sample.Tags);

			var Actual = Target.GetParameters();

			Assert.IsNull(Actual.GetAddParameters());
			Assert.IsNull(Actual.GetModifyParameters());
			Assert.IsNotNull(Actual.GetDeleteParameters());

			var DelParam = Actual.GetDeleteParameters();

			Assert.AreEqual<int>(1, DelParam.Length);
			Assert.AreEqual<string>(Sample.Caster, DelParam[0].Caster);
			Assert.AreEqual<string>(Sample.StationId, DelParam[0].StationId);
			Assert.AreEqual<int>(1, DelParam[0].TagValue.Length);
			Assert.AreEqual<string>(Sample.Tags[0].Value, DelParam[0].TagValue[0]);

		}

		[TestMethod]
		public void DeleteTest1()
		{
			var Sample = GetSample(10);
			Target.Delete(Sample.StationId, Sample.Caster, Sample.Tags);

			var Params = Target.GetParameters();

			Assert.AreEqual<int>(1, Params.GetDeleteParameters().Length);

			var Actual = Params.GetDeleteParameters()[0];

			Assert.AreEqual<int>(1, Actual.TagValue.Length);
			Assert.AreEqual<string>(Sample.Tags[0].Value, Actual.TagValue[0]);
		}

		[TestMethod]
		public void MultiDeleteTest()
		{
			var Sample0 = GetSample(1);
			var Sample1 = GetSample(1);

			Target.Delete(Sample0.StationId, Sample0.Caster, Sample0.Tags);
			Target.Delete(Sample1.StationId, Sample1.Caster, Sample1.Tags);

			Assert.AreEqual<int>(2, Target.GetParameters().GetDeleteParameters().Length);

			Target = new OneWayTransactor();

			Sample1.StationId = Sample0.StationId;
			Sample1.Caster = Sample0.Caster;

			Target.Delete(Sample0.StationId, Sample0.Caster, Sample0.Tags);
			Target.Delete(Sample1.StationId, Sample1.Caster, Sample1.Tags);

			var Params = Target.GetParameters();

			Assert.AreEqual<int>(1, Params.GetDeleteParameters().Length);
			Assert.AreEqual<int>(1, Params.GetDeleteParameters()[0].TagValue.Length);
		}

		/// <summary>
		///Add のテスト
		///</summary>
		[TestMethod()]
		public void AddTest()
		{
			var Sample = GetSample(1);
			Target.Add(Sample.StationId, Sample.Caster, Sample.Tags);

			var Params = Target.GetParameters();

			Assert.IsNull(Params.GetDeleteParameters());
			Assert.IsNull(Params.GetModifyParameters());
			Assert.IsNotNull(Params.GetAddParameters());

			Assert.AreEqual<int>(1, Params.GetAddParameters().Length);


			var Actual = Params.GetAddParameters()[0];
			Assert.AreEqual<int>(1, Actual.TagValue.Length);
			Assert.AreEqual<string>(Sample.Caster, Actual.Caster);
			Assert.AreEqual<string>(Sample.StationId, Actual.StationId);
		}

		[TestMethod]
		public void MultiTagAddTest()
		{
			var Sample = GetSample(5);
			Target.Add(Sample.StationId, Sample.Caster, Sample.Tags);

			var Actual = Target.GetParameters().GetAddParameters()[0];
			Assert.AreEqual<int>(3, Actual.TagValue.Length);

			for (int i = 0; i < 3; i++)
			{
				Assert.AreEqual<string>(Sample.Tags[i].Value, Actual.TagValue[i]);
			}
		}

		[TestMethod]
		public void MultiLiveInfoAddTest()
		{
			var Sample0 = GetSample(3);
			var Sample1 = GetSample(2);

			Target.Add(Sample0.StationId, Sample0.Caster, Sample0.Tags);
			Target.Add(Sample1.StationId, Sample1.Caster, Sample1.Tags);

			var Params = Target.GetParameters();
			Assert.AreEqual<int>(2, Params.GetAddParameters().Length);
		}

		[TestMethod]
		public void SingleModifyTest()
		{
			var AddSample = GetSample(3);
			var DelSample = GetSample(3);

			DelSample.StationId = AddSample.StationId;
			DelSample.Caster = AddSample.Caster;

			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);
			Target.Delete(DelSample.StationId, DelSample.Caster, DelSample.Tags);

			var Params = Target.GetParameters();

			Assert.IsNull(Params.GetAddParameters());
			Assert.IsNull(Params.GetDeleteParameters());
			Assert.AreEqual<int>(1, Params.GetModifyParameters().Length);

			var Actual = Params.GetModifyParameters()[0];

			Assert.AreEqual<int>(3, Actual.Tags.Length);

			for (int i = 0; i < Actual.Tags.Length; i++)
			{
				Assert.AreEqual<string>(AddSample.Tags[i].Value, Actual.Tags[i].ModifyTo);
				Assert.AreEqual<string>(DelSample.Tags[i].Value, Actual.Tags[i].ModifyFrom);
			}
		}

		[TestMethod]
		public void AsymmetryModifyTest0()
		{
			var AddSample = GetSample(2);
			var DelSample = GetSample(3);

			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);
			Target.Delete(AddSample.StationId, AddSample.Caster, DelSample.Tags);

			var Params = Target.GetParameters();

			Assert.AreEqual<int>(1, Params.GetDeleteParameters().Length);
			Assert.AreEqual<int>(1, Params.GetModifyParameters().Length);
			Assert.IsNull(Params.GetAddParameters());

			var ActDel = Params.GetDeleteParameters()[0];
			var ActMod = Params.GetModifyParameters()[0];

			Assert.AreEqual<int>(1, ActDel.TagValue.Length);
			Assert.AreEqual<int>(2, ActMod.Tags.Length);

			Assert.AreEqual<string>(DelSample.Tags[2].Value, ActDel.TagValue[0]);




			AddSample = GetSample(10);
			DelSample = GetSample(12);

			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);
			Target.Delete(AddSample.StationId, AddSample.Caster, DelSample.Tags);

			Params = Target.GetParameters();

			Assert.AreEqual<int>(1, Params.GetDeleteParameters().Length);
			Assert.AreEqual<int>(1, Params.GetModifyParameters().Length);
			Assert.IsNull(Params.GetAddParameters());

			ActDel = Params.GetDeleteParameters()[0];
			ActMod = Params.GetModifyParameters()[0];

			Assert.AreEqual<int>(1, ActDel.TagValue.Length);
			Assert.AreEqual<int>(3, ActMod.Tags.Length);

			Assert.AreEqual<string>(DelSample.Tags[3].Value, ActDel.TagValue[0]);
		}


		[TestMethod]
		public void symmetryModifyTest1()
		{
			var AddSample = GetSample(3);
			var DelSample = GetSample(2);

			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);
			Target.Delete(AddSample.StationId, AddSample.Caster, DelSample.Tags);

			var Params = Target.GetParameters();
			var ActMod = Params.GetModifyParameters()[0];
			var ActAdd = Params.GetAddParameters()[0];

			Assert.IsNull(Params.GetDeleteParameters());
			Assert.AreEqual<int>(2, ActMod.Tags.Length);
			Assert.AreEqual<int>(1, ActAdd.TagValue.Length);

			AddSample.Tags = GetSample(10).Tags;
			DelSample.Tags = GetSample(5).Tags;

			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);
			Target.Delete(AddSample.StationId, AddSample.Caster, DelSample.Tags);

			Params = Target.GetParameters();
			ActMod = Params.GetModifyParameters()[0];
			ActAdd = Params.GetAddParameters()[0];

			Assert.IsNull(Params.GetDeleteParameters());
			Assert.AreEqual<int>(3, ActMod.Tags.Length);
			Assert.AreEqual<int>(3, ActAdd.TagValue.Length);
		}

		[TestMethod]
		public void GetPrameterToResetStateTest()
		{
			var AddSample = GetSample(10);
			Target.Add(AddSample.StationId, AddSample.Caster, AddSample.Tags);

			Target.GetParameters();

			var Act = Target.GetParameters();

			Assert.IsNull(Act.GetAddParameters());
			Assert.IsNull(Act.GetDeleteParameters());
			Assert.IsNull(Act.GetModifyParameters());

		}



		private static string GetId(string Prefix)
		{
			if (Prefix != null)
			{
				return string.Format("{0}_{1}", Prefix, IdSeed++);
			}
			else
			{
				return IdSeed++.ToString();
			}
		}

		private static TagValues GetSample(int TagCount)
		{
			TagValues tmp = new TagValues();
			tmp.StationId = GetId("Station");
			tmp.Caster = GetId("Caster");

			for (int i = 0; i < TagCount; i++)
			{
				tmp.Tags.Add(new TagModel(GetId("Tag"), TagKind.User));
			}

			return tmp;
		}

	}
}
